package visual.ontogrator.pkg2;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 *
 * @author Gabriel
 */
public class SearchEngine {

    private static String tairbuscasite = "http://arabidopsis.org/tools/bulk/microarray/index.jsp";
    private static String tairsite = "http://arabidopsis.org/servlets/TairObject?type=locus&name=";
    private static String ncbisite = "http://www.ncbi.nlm.nih.gov/sites/entrez?db=gene&cmd=search&term=";
    private static String ncbiprotsite = "http://www.ncbi.nlm.nih.gov/protein/";
    private static String keggsite = "http://www.genome.jp/dbget-bin/www_bget?ath:";
    private static String yeastsite = "http://www.yeastgenome.org/cgi-bin/locus.fpl?locus=";
    private static int timeout = 10000;

    public static void main(String[] args) throws IOException, SQLException, InterruptedException {
        //comentar todo o codigo
        String //locus = "AT2G01140",
                //locus = "",
                locus = "AT5G54770",
                genenome = "cln3",
                parametros = "",
                geneID = "";

        String[] vparametros = {
            "Cln3",
            "SBF",
            "MBF",
            "Cln2",
            "Sic1",
            "Clb5",
            "Cdh1",
            "Clb2",
            "Mcm1",
            "Cdc20",
            "Cdc14",
            "Swi5"
        };

        String[] yinfo = {
            "Standard Name",
            "Systematic Name",
            "Alias",
            "Feature Type",
            "Description",
            "Name Description",
            "Chromosomal Location"
        };

        String[] kegg[] = null,
                tair[] = null,
                yeast[] = null,
                ncbi[] = null;
        /* try {
        System.out.println(">> KEGG");
        kegg = kegg(locus);
        } catch (Exception e) {
        System.out.println(e);
        System.out.println("Erro ao capturar informacoes do KEGG");
        }
        
        
        try {
        System.out.println(">> TAIR");
        tair = tair(locus);
        } catch (Exception e) {
        System.out.println(e);
        System.out.println("Erro ao capturar informacoes do TAIR");
        }*/
        Gene gene = new Gene();
        try {
            System.out.println(">> YEAST");
             yeast = yeast(genenome,gene);
        } catch (Exception e) {
            System.out.println(e);
            System.out.println("Erro ao capturar informacoes do YEAST");
        }
        
        imprimirPontoVirgula(yinfo);
       
        for (int i = 0; i < vparametros.length; i++) {
//            imprimirPontoVirgula(matrixToVector(yeast(vparametros[i])));
        }

        /* try {
        System.out.println(">> NCBI");
        
        
        if(!parametros.equals("")){
        geneID = ncbiNome(parametros);
        }
        
        if (geneID.equals("")) {
        for (int i = 0; i < kegg[2].length; i++) {
        if (kegg[2][i].startsWith("NCBI-GeneID:")) {
        geneID = kegg[2][i + 1];
        }
        }
        }
        
        ncbi = ncbi(geneID);
        } catch (Exception e) {
        System.out.println(e);
        System.out.println("Erro ao capturar informacoes do NCBI");
        }
        
         */


        /* imprimirPontoVirgula(info);
        for(int i=0;i<vparametros.length;i++){
        imprimirPontoVirgula(matrixToVector(ncbi(ncbiNome(vparametros[i]))));
        }*/
    }

    private static String getTable(Elements table) {
        String annotation = "";
        try {


            Iterator tIter = table.select("tbody td").iterator();

            //enquanto o interator conter elementos
            while (tIter.hasNext()) {

                //strings para guardarem as colunas da tabela annotations
                String col1 = "", col2 = "", col3 = "";


                for (int i = 1; i <= 5; i++) {
                    //se existirem elementos no iterator
                    if (tIter.hasNext()) {
                        //variavel auxiliar td que contem o elemento atual
                        Element td = (Element) tIter.next();

                        //a tabela em html possui 5 colunas sendo 2 delas vazias (2 e 4) portanto so capturar colunas 1, 3 e 5
                        switch (i) {
                            case 1:
                                col1 = td.text();
                                break;

                            case 3:
                                col2 = td.text();
                                break;

                            case 5:
                                col3 = td.text();
                                break;
                        }
                    }
                }

                //se não existirem mais elementos a tabela acabou
                if (tIter.hasNext()) {
                    if (col2.equals("functions in")) {
                        annotation = annotation + ", " + col3;
                    }

                    if (col2.equals("has")) {
                        annotation = annotation + ", " + col3;
                    }

                    if (col2.equals("located in")) {
                        annotation = annotation + ", " + col3;
                    }
                    //System.out.println(col1 + "\t" + col2 + "\t" + col3 + "\t");
                }
            }



        } catch (Exception e) {
            System.out.println(e);
            System.out.println("Informacao nao encontrada");
        }

        return annotation;

    }

    private static String[] splitToken(String info, String delimiter) {

        //cria delimitador das palavras

        String token = "";


        StringTokenizer tokenizer = new StringTokenizer(info, delimiter);

        //cria uma lista para armazenar os tokens
        String lista[] = new String[tokenizer.countTokens()];

        //percorre o tokenizer ate nao ter mais palavras 
        int i = 0;
        while (tokenizer.hasMoreTokens()) {
            //token recebe o valor da palavra atual do tokenizer
            token = tokenizer.nextToken();

            //se a palavra comecar com "espaco" retirar o priemiro caractere("espaco")

            if (token.startsWith(" ")) {
                token = token.substring(1);
            }

            //System.out.println("A palavra adicionada foi >>" + token);

            //adicionar palavar quebrada
            lista[i] = token;
            i++;
        }
        return lista;
    }

    private static void imprimirLista(String lista[]) {
        for (int i = 0; i < lista.length; i++) {
            System.out.println(lista[i]);
        }
    }

    private static void imprimir(String[] matriz[], String[] info) {
        for (int i = 0; i < info.length; i++) {
            System.out.println(info[i]);
            if (matriz[i] != null) {
                imprimirLista(matriz[i]);
            }
            System.out.println("--------------------------");
        }
    }

    private static String[] matrixToVector(String[] matriz[]) {
        String vetor[] = new String[matriz.length];

        for (int i = 0; i < matriz.length; i++) {
            try {
                vetor[i] = matriz[i][0];
            } catch (Exception e) {
                vetor[i] = "";
            }
            try {
                for (int j = 1; j < matriz[i].length; j++) {
                    try {
                        vetor[i] = vetor[i] + ", " + matriz[i][j];
                    } catch (Exception e) {
                    }
                }
            } catch (Exception e) {
            }
        }

        return vetor;
    }

    private static void imprimirPontoVirgula(String[] vetor) {
        String info;
        info = vetor[0];
        for (int i = 1; i < vetor.length; i++) {
            info = info + "\t" + vetor[i];
        }
        System.out.println(info);
    }

    private static Elements[] capturaTabela(String[] info, Elements tabela, String css) {
        StringTokenizer tokenizer = new StringTokenizer(css, " ");
        int nparent = tokenizer.countTokens();
        //System.out.println(nparent);

        Elements linhas[] = new Elements[info.length];
        
        for (int i = 0; i < info.length; i++) {
            try {
                String contains = ":contains(" + info[i] + ")";
                Element nome = tabela.select(css).select(contains).first();

                //capturar o elemento pai tr
                for (int j = 0; j < nparent; j++) {

                    nome = nome.parent();
                }

                //capturar td
                linhas[i] = nome.children();

            } catch (Exception e) {
                System.out.println(e);
                System.out.println("Informacao " + info[i] + " nao encontrada");

            }
        }

        return linhas;
    }

    private static String[][] geraMatriz(String[] info, Elements[] linhas, String[] cssLinha, String[] delimiter) {
        String[] matriz[] = new String[info.length][];
        for (int i = 0; i < info.length; i++) {
            if (linhas[i] != null) {
                //Captura o texto do elemento da tabela de acordo com o css  e joga na função split para quebrar as palavras e retornar un Strin[];
                matriz[i] = splitToken(linhas[i].select(cssLinha[i]).text(), delimiter[i]);
            }
        }
        return matriz;



    }

    public static String[][] tair(String locus, Gene gene) throws IOException {

        //extrair da tabela
        //functions in
        // located in
        // has
        /*
        
        Informações para capturar
        (x) Description 
        (x) Gene Model Type
        (x) Other names:
        (x) Annotations
        ( ) Keyword ID
        ( ) GO:
        
         */


        //caminhos css para a tabela principal do tair
        String csstable = "div#content.clearfix table tbody tr";

        //vetor com os nomes das linhas que serão capturadas
        String info[] = {
            "Description",
            "Gene Model Type",
            "Other names:",
            "Annotations"
        };

        String[] matriz[] = new String[info.length][];

        Elements linhas[] = new Elements[info.length];
       
        try{
        //carregar página do tair em um documento
        Document doc = Jsoup.connect(tairsite + locus).timeout(timeout).get();

        //extrair tabela principal do tair
        Elements tabela = doc.select(csstable);

        linhas = capturaTabela(info, tabela, "th");

        //localização dos elementos respectivos ao info[] da tabela extraida
        String[] cssLinha = {"td:eq(2)",
            "td:eq(2)",
            "td:eq(2)",
            "td"
        };

        //divisor da informação respectiva ao info[]
        String[] delimiter = {";",
            "",
            ",",
            ","
        };

        //capturar infromações
        matriz = geraMatriz(info, linhas, cssLinha, delimiter);

        //adicionar tabela annotations
        if (linhas[info.length - 1] != null) {
            matriz[info.length - 1] = splitToken(getTable(linhas[info.length - 1].select(cssLinha[info.length - 1])), delimiter[info.length - 1]);
        }

        imprimir(matriz, info);
        try{gene.setDescription(popGene(gene.getDescription(), matriz[0]));}catch(Exception e){};
        try{gene.setGene_Model_Type(popGene(gene.getGene_Model_Type(), matriz[1]));}catch(Exception e){};
        try{gene.setOther_names(popGene(gene.getOther_names(), matriz[2]));}catch(Exception e){};
        try{gene.setAnnotations(popGene(gene.getAnnotations(), matriz[3]));}catch(Exception e){};
        
        //validar se os dados foram capturados com sucesso
        gene.setValidarTAIR(true);
        }catch(Exception e){
            System.out.println("Erro ao capturara dados no TAIR");
            System.out.println(e);
            //dados não foram capturados com sucesso nao validar a captura
            gene.setValidarTAIR(false);
        }
        return matriz;

    }

    public static String[][] kegg(String locus, Gene gene) throws IOException {
        //comentar
        //others dbs capturar somente geneid 
        //module e patheway fazer algoritmo tabela e capturar os codigos

        /*
        
        Informações para capturar
        (x) Definition
        (x) Module
        (x) Other DBs
        (x) Pathway
        
         */

        //caminhos css para a tabela principal do kegg
        String csstable = "td.fr1 tbody tr";


        String info[] = {"Definition",
            "Module",
            "Other DBs",
            "Pathway"};

        String[] matriz[] = new String[info.length][];
        Elements linhas[] = new Elements[info.length];
        
        try{
        Document doc = Jsoup.connect(keggsite + locus).timeout(timeout).get();

        Elements tabela = doc.select(csstable);

        linhas = capturaTabela(info, tabela, "th nobr");

        String[] cssLinha = {"td",
            "td nobr",
            "td",
            "td nobr"
        };

        String[] delimiter = {",",
            " ",
            " ",
            " "
        };

        matriz = geraMatriz(info, linhas, cssLinha, delimiter);
        //popular genes
        try{gene.setDefinition(popGene(gene.getDefinition(), matriz[0]));}catch(Exception e){};
        try{gene.setModule(popGene(gene.getModule(), matriz[1]));}catch(Exception e){};
        try{gene.setOther_DBs(popGene(gene.getOther_DBs(), matriz[2]));}catch(Exception e){};
        try{gene.setPathway(popGene(gene.getPathway(), matriz[3]));}catch(Exception e){};
        
        imprimir(matriz, info);
        
        //validar se os dados foram capturados com sucesso
        gene.setValidarKEGG(true);
        }catch(Exception e){
            System.out.println("Erro ao capturara dados no KEGG");
            System.out.println(e);
            //dados não foram capturados com sucesso nao validar a captura
            gene.setValidarKEGG(false);
        }
        return matriz;

    }

    private static String ncbiNome(String parametros) throws IOException {

        /*
        dados de entrada
         * GENE;função
        Cln3;cyclin
        SBF;TranscriptionFactor
        MBF;TranscriptionFactor
        Cln2;cyclin
        Sic1;inhibitors
        Clb5;cyclin
        Cdh1;inhibitors
        Clb2;cyclin
        Mcm1/SFF;TranscriptionFactor
        Cdc20/Cdc14;inhibitors
        Swi5;TranscriptionFactor
        
         */
        String geneID = "";
        String strparam = "";
        String[] lista = splitToken(parametros, ";");

        for (int i = 0; i < lista.length; i++) {
            strparam = strparam + "+" + lista[i];
        }

        Document doc = Jsoup.connect(ncbisite + strparam).timeout(timeout).get();
        //System.out.println(ncbisite+strparam);
        Elements busca = doc.select("div.rprt");
        int[] score = new int[busca.size()];
        for (int i = 0; i < busca.size(); i++) {
            Elements topico = busca.select(":eq(" + i + ")").select("div.rslt p.title");
            Elements negrito = topico.select("b");

            if (topico.text().substring(0, lista[0].length()).toUpperCase().equals(lista[0].toUpperCase())) {
                // System.out.println(topico.text().substring(0, lista[0].length())+" = "+lista[0].toUpperCase());
                score[i] += 2;
            }

            for (int j = 0; j < negrito.size(); j++) {
                if (negrito.select(":eq(" + j + ")").text().toLowerCase().equals(lista[1].toLowerCase())) {
                    score[i] += 1;
                    j = negrito.size();
                }
            }

            //  System.out.println(i+"  "+topico.text());
        }

        int highscore = 0,
                index = 0;
        for (int i = 0; i < score.length; i++) {
            //  System.out.println("Score "+i+" = "+score[i]);
            if (score[i] > highscore) {
                highscore = score[i];
                index = i;
            }
        }
        // System.out.println("High Score = "+index);

        geneID = busca.select(":eq(" + Integer.toString(index) + ")").select("div.rslt div.aux div.resc dl.rprtid dd").text();
        //busca.select(":eq("+i+")").select("div.rslt p.title")

        // System.out.println(geneID);
        return geneID;
    }

    public static String[][] ncbi(String geneid, Gene gene) throws IOException {

        /*
        
        Informações para capturar
        (x) Gene symbol
        (x) Gene description
        (x) Primary source
        (x) Locus tag
        (x) Gene type
        (x) RNA name
        (x) RefSeq status
        (x) Organism
        (x) Lineage
        (x) Also known as
        (x) Summary
        (x) Location
        (x) ID Protein
        
         */

        String info[] = {
            "Official Symbol",
            "Official Full Name",
            "See related",
            "Gene symbol",
            "Gene description",
            "Primary source",
            "Locus tag",
            "Gene type",
            "RNA name",
            "RefSeq status",
            "Organism",
            "Lineage",
            "Also known as",
            "Summary",
            "Sequence",
            "Location",
            "ID Protein"
        };

        String delimiter[] = {
            "",
            ",",
            ";",
            "",
            "",
            "",
            "",
            "",
            "",
            "",
            "",
            ";",
            ";",
            "",
            "",
            "",
            ""
        };

        String[] matriz[] = new String[info.length][];
        try{
        //capturar site pelo gene id
        Document doc = Jsoup.connect(ncbisite + geneid).timeout(timeout).get();

        //capturar tabela
        Elements table = doc.select("dl#summaryDl");

        //capturar celula 1
        Elements dt = table.select("dt");

        //capturar celula2
        Elements dd = table.select("dd");

        //criar 1 iterator para cada celula
        Iterator dtIter = dt.iterator();
        Iterator ddIter = dd.iterator();

        //percorrer todas as linhas
        while (dtIter.hasNext()) {
            String col1, col2;

            //celula 1 da linha
            Element edt = (Element) dtIter.next();
            col1 = edt.text();

            //celula 2 da linha
            Element edd = (Element) ddIter.next();
            col2 = edd.text();
            
            for (int i = 0; i < info.length; i++) {
                if (info[i].equals(col1)) {
                    matriz[i] = splitToken(col2, delimiter[i]);
                }
            }
        }


        //Capturar chromossome
        Elements location = doc.select("dl.margin_bt0").select("dd.magin_top_m1");
        matriz[info.length - 2] = splitToken(location.text(), delimiter[info.length - 2]);
        
        //Capturar sequence
  
        Elements sequence = doc.select("dl.chr_location").select("dd.magin_top_m1");
        matriz[info.length - 3] = splitToken(sequence.text(), delimiter[info.length - 3]);

        
        //capturar ID Protein
        Elements idprotein = doc.select("div.gene-proteinInfo").select("dt.heading");
        matriz[info.length - 1] = splitToken(idprotein.text(), delimiter[info.length - 1]);

        //popular genes
        
        try{gene.setOfficial_Symbol(popGene(gene.getOfficial_Symbol(), matriz[0]));}catch(Exception e){};
        try{gene.setOfficial_Full_Name(popGene(gene.getOfficial_Full_Name(), matriz[1]));}catch(Exception e){};
        try{gene.setSee_related(popGene(gene.getSee_related(), matriz[2]));}catch(Exception e){};
        try{gene.setGene_symbol(popGene(gene.getGene_symbol(), matriz[3]));}catch(Exception e){};
        try{gene.setGene_description(popGene(gene.getGene_description(), matriz[4]));}catch(Exception e){};
        try{gene.setPrimary_source(popGene(gene.getPrimary_source(), matriz[5]));}catch(Exception e){};
        try{gene.setLocus_tag(popGene(gene.getLocus_tag(), matriz[6]));}catch(Exception e){};
        try{gene.setGene_type(popGene(gene.getGene_type(), matriz[7]));}catch(Exception e){};
        try{gene.setRNA_name(popGene(gene.getRNA_name(), matriz[8]));}catch(Exception e){};
        try{gene.setRefSeq_status(popGene(gene.getRefSeq_status(), matriz[9]));}catch(Exception e){};
        try{gene.setOrganism(popGene(gene.getOrganism(), matriz[10]));}catch(Exception e){};
        try{gene.setLineage(popGene(gene.getLineage(), matriz[11]));}catch(Exception e){};
        try{gene.setAlso_known_as(popGene(gene.getAlso_known_as(), matriz[12]));}catch(Exception e){};
        try{gene.setSummary(popGene(gene.getSummary(), matriz[13]));}catch(Exception e){};
        try{gene.setSequence(popGene(gene.getSequence(), matriz[14]));}catch(Exception e){};
        try{gene.setLocation(popGene(gene.getLocation(), matriz[15]));}catch(Exception e){};
        try{gene.setID_Protein(popGene(gene.getID_Protein(), matriz[16]));}catch(Exception e){};
        
        imprimir(matriz,info);
         //validar se os dados foram capturados com sucesso
        gene.setValidarNCBI(true);
        }catch(Exception e){
            System.out.println("Erro ao capturara dados no NCBI");
            System.out.println(e);
            //dados não foram capturados com sucesso nao validar a captura
            gene.setValidarNCBI(false);
        }
        return matriz;
    }

    public static String[][] yeast(String genenome, Gene gene) throws IOException {

        String[] info = {
            "Standard Name",
            "Systematic Name",
            "Alias",
            "Feature Type",
            "Description",
            "Name Description",
            "Chromosomal Location"
        };

        String[] delimiter = {
            "",
            "",
            ",",
            ",",
            ";",
            "",
            ""
        };

        String[] cssLinha = {
            "td",
            "td",
            "td",
            "td",
            "td",
            "td",
            "td"
        };

        String csstable = "div#left_side_content tr";

        String[] matriz[] = new String[info.length][];
        try{
        Document doc = Jsoup.connect(yeastsite + genenome).timeout(timeout).get();

        Elements linhas[] = new Elements[info.length];

        //extrair tabela principal do tair
        Elements tabela = doc.select(csstable);

        //buscar linhas e guardar elementos 
        linhas = capturaTabela(info, tabela, "th");

        matriz = geraMatriz(info, linhas, cssLinha, delimiter);

        imprimir(matriz, info);

        //popular os genes
        try{gene.setStandard_Name(popGene(gene.getStandard_Name(), matriz[0]));}catch(Exception e){};
        try{gene.setSystematic_Name(popGene(gene.getSystematic_Name(), matriz[1]));}catch(Exception e){};
        try{gene.setAlias(popGene(gene.getAlias(), matriz[2]));}catch(Exception e){};
        try{gene.setFeature_Type(popGene(gene.getFeature_Type(), matriz[3]));}catch(Exception e){};
        try{gene.setDescription(popGene(gene.getDescription(), matriz[4]));}catch(Exception e){};
        try{gene.setName_Description(popGene(gene.getName_Description(), matriz[5]));}catch(Exception e){};
        try{gene.setChromosomal_Location(popGene(gene.getChromosomal_Location(), matriz[6]));}catch(Exception e){};
       //validar se os dados foram capturados com sucesso
        gene.setValidarYEAST(true);
        }catch(Exception e){
            System.out.println("Erro ao capturara dados no YEAST");
            System.out.println(e);
            //dados não foram capturados com sucesso nao validar a captura
            gene.setValidarYEAST(false);
        }
        return matriz;

    }

    //Procedimentos para pupular os genes
    //procedimento para adicionar novos valores ao array, além dos existentes
    private static ArrayList<String> popGene(ArrayList<String> gene, String[] info) {
        gene.addAll(Arrays.asList(info));
        return gene;
    }
}
